package com.kvest.scanrecognizer.service;

import android.app.IntentService;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import com.kvest.scanrecognizer.R;
import com.kvest.scanrecognizer.contentprovider.ScanRecognizerProviderMetadata;
import com.kvest.scanrecognizer.core.Settings;
import com.kvest.scanrecognizer.datamodel.RecognizeStatus;
import com.kvest.scanrecognizer.datastorage.table.RecognizeItemTable;
import com.kvest.scanrecognizer.network.NetworkRequestHelper;
import com.kvest.scanrecognizer.network.response.RecognizeResponse;
import com.kvest.scanrecognizer.network.response.StatusResponse;
import com.kvest.scanrecognizer.utility.FileUtility;
import com.kvest.scanrecognizer.utility.FormatUtils;
import com.kvest.scanrecognizer.utility.Utils;

import java.io.File;

public class NetworkService extends IntentService {
    public static final String START_ACTION = "com.kvest.scanrecognizer.service.NetworkService.START_ACTION";
    public static final String STOP_ACTION = "com.kvest.scanrecognizer.service.NetworkService.STOP_ACTION";
    public static final String MESSAGE_ACTION = "com.kvest.scanrecognizer.service.NetworkService.STOP_MESSAGE";
    //Data for messages
    public static final String MESSAGE_TYPE_EXTRA = "com.kvest.scanrecognizer.service.NetworkService.MESSAGE_TYPE";
    public static final int MESSAGE_TYPE_INFO = 0;
    public static final int MESSAGE_TYPE_ERROR = 1;
    public static final String MESSAGE_TEXT_EXTRA = "com.kvest.scanrecognizer.service.NetworkService.MESSAGE_TEXT";

    public static final String IMAGE_PATH_EXTRA = "com.kvest.scanrecognizer.service.NetworkService.IMAGE_PATH";
    public static final String ROTATION_EXTRA = "com.kvest.scanrecognizer.service.NetworkService.ROTATION";
    public static final String ACTION_CODE_EXTRA = "com.kvest.scanrecognizer.service.NetworkService.ACTION_CODE";
    public static final String UID_EXTRA = "com.kvest.scanrecognizer.service.NetworkService.UID";
    public static final String FORMAT_EXTRA = "com.kvest.scanrecognizer.service.NetworkService.FORMAT";
    public static final int ACTION_CODE_SEND_IMAGE = 0;
    public static final int ACTION_CODE_DOWNLOAD = 1;
    public static final int ACTION_CODE_UPDATE_STATES = 2;
    public static final int ACTION_CODE_SEND_EMAIL = 3;
    public static final int ACTION_CODE_SHARE = 4;

    public NetworkService() {
        super("RecognizerNetworkService");
    }

    @Override
    public void onCreate() {
        super.onCreate();

        LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(START_ACTION));
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(STOP_ACTION));
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        switch (intent.getIntExtra(ACTION_CODE_EXTRA, -1)) {
            case ACTION_CODE_SEND_IMAGE : onSendImage(intent); break;
            case ACTION_CODE_DOWNLOAD : onDownload(intent); break;
            case ACTION_CODE_UPDATE_STATES : onUpdateStates(intent); break;
            case ACTION_CODE_SEND_EMAIL: onSendEmail(intent); break;
            case ACTION_CODE_SHARE: onShare(intent); break;
        }
    }

    private void messageNotification(int messageType, String text) {
        Intent intent = new Intent(MESSAGE_ACTION);
        intent.putExtra(MESSAGE_TYPE_EXTRA, messageType);
        intent.putExtra(MESSAGE_TEXT_EXTRA, text);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }

    private void onUpdateStates(Intent intent) {
        //send request
        String[] uids = getWaitingUIDs();
        if (uids.length > 0) {
            StatusResponse[] result = NetworkRequestHelper.getStatuses(uids);

            //save states
            ContentResolver resolver = getContentResolver();
            for (StatusResponse item : result) {
                ContentValues values = new ContentValues(1);
                values.put(RecognizeItemTable.STATUS_COLUMN, item.getStatus().getInt());
                resolver.update(ScanRecognizerProviderMetadata.RECOGNIZE_ITEMS_URI, values,
                                RecognizeItemTable.UID_COLUMN + "=?", new String[]{item.uid});
            }
        }
    }

    private void onShare(Intent intent) {
        //download file
        String uid = "";
        if (intent.hasExtra(UID_EXTRA)) {
            uid = intent.getStringExtra(UID_EXTRA);
        }
        int format = intent.getIntExtra(FORMAT_EXTRA, FormatUtils.TXT_FORMAT);

        String name = getNameByUid(uid);
        if (TextUtils.isEmpty(name)) {
            name = uid;
        }

        name += FormatUtils.getExtentionById(format);
        String fileLocation = Settings.getInstance(getApplicationContext()).getWorkingDirectory() + name;
        boolean result = NetworkRequestHelper.download(uid, format, new File(fileLocation));

        if (result) {
            Intent sendEmailIntent = new Intent(Intent.ACTION_SEND);
            sendEmailIntent.setType("text/plain") ; //"*/*"
            sendEmailIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_subject, name));
            sendEmailIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.share_body, name));
            sendEmailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + fileLocation));
            startActivity(Intent.createChooser(sendEmailIntent, getString(R.string.sharing)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
        } else {
            messageNotification(MESSAGE_TYPE_ERROR, getString(R.string.error_downloading_file, name));
        }
    }

    private void onSendEmail(Intent intent) {
        //download file
        String uid = "";
        if (intent.hasExtra(UID_EXTRA)) {
            uid = intent.getStringExtra(UID_EXTRA);
        }
        int format = intent.getIntExtra(FORMAT_EXTRA, FormatUtils.TXT_FORMAT);

        String name = getNameByUid(uid);
        if (TextUtils.isEmpty(name)) {
            name = uid;
        }

        name += FormatUtils.getExtentionById(format);
        String fileLocation = Settings.getInstance(getApplicationContext()).getWorkingDirectory() + name;
        boolean result = NetworkRequestHelper.download(uid, format, new File(fileLocation));

        if (result) {
            Intent sendEmailIntent = new Intent(Intent.ACTION_SEND);
            sendEmailIntent.setType("message/rfc822") ; // use from live device
            sendEmailIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.mail_subject, name));
            sendEmailIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.mail_body, name));
            sendEmailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + fileLocation));
            startActivity(Intent.createChooser(sendEmailIntent, getString(R.string.mail_sending)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
        } else {
            messageNotification(MESSAGE_TYPE_ERROR, getString(R.string.error_downloading_file, name));
        }

    }

    private void onSendImage(Intent intent) {
        String imagePath = "";
        int rotation = 0;
        if (intent.getExtras().containsKey(IMAGE_PATH_EXTRA)) {
            imagePath = intent.getStringExtra(IMAGE_PATH_EXTRA);
        }
        if (intent.getExtras().containsKey(ROTATION_EXTRA)) {
            rotation = intent.getIntExtra(ROTATION_EXTRA, 0);
        }

        RecognizeResponse response = NetworkRequestHelper.recognize(imagePath, rotation,
                                                                    Utils.getClientId(getApplicationContext()));

        if (response.getCode() == RecognizeResponse.CODE_OK) {
            //save result into DB
            ContentValues values = new ContentValues(4);
            values.put(RecognizeItemTable.UID_COLUMN, response.getUid());
            values.put(RecognizeItemTable.STATUS_COLUMN, RecognizeStatus.IN_QUEUE.getInt());
            values.put(RecognizeItemTable.SEND_DATE_COLUMN, System.currentTimeMillis());
            values.put(RecognizeItemTable.NAME_COLUMN, FileUtility.getFileName(imagePath, false));
            Bitmap thumbnail = Utils.createThumbnailImage(imagePath,
                                                          (int)getResources().getDimension(R.dimen.thumbnail_size),
                                                          (int)getResources().getDimension(R.dimen.thumbnail_size),
                                                          rotation);
            values.put(RecognizeItemTable.THUMBNAIL_COLUMN, Utils.bitmapToBytearray(thumbnail));
            thumbnail.recycle();

            getContentResolver().insert(ScanRecognizerProviderMetadata.RECOGNIZE_ITEMS_URI, values);
        } else {
            int resId = R.string.server_error_recognizing;
            switch (response.getCode()) {
                case RecognizeResponse.CODE_FILE_CONVERT_ERROR : resId = R.string.server_error_recognizing; break;
                case RecognizeResponse.CODE_LIMIT_REACHED : resId = R.string.limit_reached; break;
                case RecognizeResponse.CODE_NETWORK_ERROR : resId = R.string.network_error; break;
                case RecognizeResponse.CODE_RESPONSE_PARSE_ERROR : resId = R.string.parsing_error; break;
            }
            messageNotification(MESSAGE_TYPE_ERROR, getString(resId));
        }
    }

    private String[] getWaitingUIDs() {
        Cursor cursor = getContentResolver().query(ScanRecognizerProviderMetadata.RECOGNIZE_ITEMS_URI, new String[]{RecognizeItemTable.UID_COLUMN},
                                                   RecognizeItemTable.STATUS_COLUMN + "=? OR " + RecognizeItemTable.STATUS_COLUMN + "=?",
                                                   new String[]{Integer.toString(RecognizeStatus.IN_QUEUE.getInt()),
                                                                Integer.toString(RecognizeStatus.IN_PROGRESS.getInt())},
                                                    null);
        String[] result = new String[cursor.getCount()];
        try {
            int i = 0;
            for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
                result[i++] = cursor.getString(0);
            }
        } finally {
            cursor.close();
        }

        return result;
    }

    private void onDownload(Intent intent) {
        String uid = "";
        if (intent.hasExtra(UID_EXTRA)) {
            uid = intent.getStringExtra(UID_EXTRA);
        }
        int format = intent.getIntExtra(FORMAT_EXTRA, FormatUtils.TXT_FORMAT);

        String name = getNameByUid(uid);
        if (TextUtils.isEmpty(name)) {
            name = uid;
        }

        name += FormatUtils.getExtentionById(format);
        boolean result = NetworkRequestHelper.download(uid, format, new File(Settings.getInstance(getApplicationContext()).getWorkingDirectory() + name));

        //notify the result
        if (result) {
            messageNotification(MESSAGE_TYPE_INFO, getString(R.string.file_downloaded, name, Settings.getInstance(getApplicationContext()).getShortWorkingDirectory()));
        } else {
            messageNotification(MESSAGE_TYPE_ERROR, getString(R.string.error_downloading_file, name));
        }
    }

    private String getNameByUid(String uid) {
        Cursor cursor = getContentResolver().query(ScanRecognizerProviderMetadata.RECOGNIZE_ITEMS_URI,
                                                   new String[]{RecognizeItemTable.NAME_COLUMN},
                                                   RecognizeItemTable.UID_COLUMN + "=?",
                                                   new String[]{uid},
                                                   null);
        try {
            if (cursor.moveToFirst()) {
                return cursor.getString(cursor.getColumnIndex(RecognizeItemTable.NAME_COLUMN));
            } else {
                return "";
            }
        } finally {
            cursor.close();
        }
    }
}
